package cool.taomu.toolkit.service.centre.kademlia.utils

import com.google.inject.Injector
import com.google.inject.Key
import com.google.inject.TypeLiteral
import com.google.inject.name.Names
import cool.taomu.toolkit.Context
import cool.taomu.toolkit.TaomuGuice
import cool.taomu.toolkit.utils.ReflectionsScanner
import java.lang.annotation.Annotation
import java.lang.reflect.Method
import java.util.ArrayList
import java.util.HashSet
import java.util.List
import java.util.Map
import java.util.Set
import javax.inject.Inject
import javax.ws.rs.DELETE
import javax.ws.rs.GET
import javax.ws.rs.POST
import javax.ws.rs.PUT
import javax.ws.rs.Path
import org.eclipse.xtend.lib.annotations.Accessors
import org.slf4j.LoggerFactory
import org.glassfish.jersey.uri.UriTemplate
import java.util.HashMap

@Accessors
class ResourceCollector {
    val static LOG = LoggerFactory.getLogger(ResourceCollector);

    var static HTTP_METHOD_ANNOTATIONS = #{GET -> "get", POST -> "post", PUT -> "put", DELETE -> "delete"}

    var Set<String> scanResult = new HashSet();

    @Inject
    // @Named("kademlia.resource.injector")
    Context ginjector;

    def init() {
        var r = getScanPackages(ginjector.injectorSupplier.get);
        r.forEach [
            LOG.info("scan package:{}", it)
            synchronized (this) {
                var scanR = scan(it.trim)
                scanR.forEach [ sr |
                    if (!scanResult.exists[it.equals(sr)]) {
                        scanResult.add(sr)
                    }
                ]
            }
        ]
        LOG.info("扫描到的服务:{}", scanResult)
    }

    def getScanPackages(Injector injector) {
        LOG.info("binding : {}", injector.bindings);
        val pks = new ArrayList<String>();
        try {
            if (injector.getExistingBinding(Key.get(new TypeLiteral<List<String>>() {
            }, Names.named(TaomuGuice.JESERY_PACKAGES))) !== null) {
                var pk = injector.getInstance(Key.get(new TypeLiteral<List<String>>() {
                }, Names.named(TaomuGuice.JESERY_PACKAGES)));
                pks.addAll(pk);
            }
        } catch (Exception ex) {
            LOG.debug("packages Exception:{}", ex);
        }
        try {
            if (injector.getExistingBinding(Key.get(String, Names.named(TaomuGuice.JESERY_SERVICELOADER_PACKAGES))) !==
                null) {
                var String slpk = injector.getInstance(
                    Key.get(String, Names.named(TaomuGuice.JESERY_SERVICELOADER_PACKAGES)));
                slpk.split(",").forEach [
                    pks.add(it);
                ]
            }
        } catch (Exception ex) {
            LOG.debug("packages Exception:{}", ex);
        }
        LOG.info("packages:{}", pks);
        return pks
    }

    def scan(String basePackage) {
        var resourceClasses = ReflectionsScanner.scanType(Path, basePackage)
        var result = new HashSet<String>();
        for (Class<?> clazz : resourceClasses) {
            var Path classPath = clazz.getAnnotation(Path);
            var String basePath = normalizePath(classPath.value());
            for (Method method : clazz.getDeclaredMethods()) {
                for (Map.Entry<Class<? extends Annotation>, String> entry : HTTP_METHOD_ANNOTATIONS.entrySet()) {
                    if (method.isAnnotationPresent(entry.getKey())) {
                        var String httpMethod = entry.getValue().toUpperCase;
                        var String methodPath = "";
                        if (method.isAnnotationPresent(Path)) {
                            methodPath = method.getAnnotation(Path).value().normalizePath;
                        }
                        var String fullPath = basePath.mergePaths(methodPath);
                        // 格式：get:/users 或 post:/users/create
                        result.add(httpMethod + ":" + fullPath);
                    }
                }
            }
        }
        return result;
    }

    // 确保路径以 / 开头且不重复
    private def String normalizePath(String path) {
        if (path === null || path.isEmpty()) {
            return "";
        }
        return path.startsWith("/") ? path : "/" + path;
    }

    // 合并类路径和方法路径
    private def String mergePaths(String classPath, String methodPath) {
        if (classPath === null || classPath.isEmpty()) {
            return methodPath;
        }
        if (methodPath === null || methodPath.isEmpty()) {
            return classPath;
        }

        // 去掉两边多余的斜杠再合并
        var String cleanedClassPath = classPath.replaceAll("/+$", "");
        var String cleanedMethodPath = methodPath.replaceAll("^/+", "");

        return cleanedClassPath + (cleanedMethodPath.isEmpty() ? "" : "/" + cleanedMethodPath);
    }

    def boolean matchesAnyTemplate(String path) {
        LOG.info("\n模板数量:{} \n模板匹配: {} ", scanResult, path)
        for (String template : scanResult) {
            var uriTemplate = new UriTemplate(template);
            if (uriTemplate.match(path, new HashMap())) {
                LOG.info("模板匹配:true")
                return true;
            }
        }
        LOG.info("模板匹配:false")
        return false;
    }
}
